﻿using Microsoft.VisualBasic;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.Configuration;
using System.ComponentModel;
using System.IO;
using System.IO.Compression;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Web.SessionState;
using System.Web.UI;
using iTextSharp.text.pdf;
using iTextSharp.text;


namespace Adex
{
    public enum ViewStateConfig
    {
        Session,
        Compress,
        Cache,
        Default,
        NotSet
    }

    public partial class BasePage : System.Web.UI.Page
    {
        private const string ViewStateModeSetting = "ViewStateMode";
        private const string ViewStateSessionId = "ViewStateSessionId";
        private const string CompressedViewStateId = "CompressedViewState";

        private const string ViewStateCacheId = "ViewStateCacheId";
        private ViewStateConfig _viewStateMode = ViewStateConfig.NotSet;
 

        [Browsable(true)]
        [Category("Behaviour")]
        [DefaultValue(ViewStateConfig.NotSet)]
        public ViewStateConfig ViewStateMode
        {

            get
            {
                //The setting on the page overrdes the one on the site config. 
                if (_viewStateMode != ViewStateConfig.NotSet)
                {
                    return _viewStateMode;
                }
                else if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings[ViewStateModeSetting]))
                {
                    return (ViewStateConfig)Enum.Parse(typeof(ViewStateConfig), ConfigurationManager.AppSettings[ViewStateModeSetting], true);
                }
                else
                {
                    return ViewStateConfig.Default;
                }
            }
            set { _viewStateMode = value; }
        }

        protected override void SavePageStateToPersistenceMedium(object state)
        {
            switch (ViewStateMode)
            {
                case ViewStateConfig.Session:
                    //Since the session isn't always availible, we had better make sure we 
                    //do something sensible 
                    if (this.Session.Mode != SessionStateMode.Off)
                    {
                        this.SaveToSession(state);
                    }
                    else
                    {
                        this.CompressViewstate(state);
                    }
                    break; 
 
                case ViewStateConfig.Compress:
                    this.CompressViewstate(state);
                    break;  
 
                case ViewStateConfig.Cache:
                    this.SaveToCache(state);
                    break;
                default:
                    base.SavePageStateToPersistenceMedium(state);
                    break; 
 
            }
        }

        protected override object LoadPageStateFromPersistenceMedium()
        {
            switch (ViewStateMode)
            {
                case ViewStateConfig.Session:
                    if (this.Session.Mode != SessionStateMode.Off)
                    {
                        return this.LoadFromSession();
                    }
                    else
                    {
                        return this.DecompressViewstate();
                    }
 
                case ViewStateConfig.Compress:

                    return this.DecompressViewstate();
                case ViewStateConfig.Cache:

                    return this.LoadFromCache();
                default:
                    return base.LoadPageStateFromPersistenceMedium();
            }
        }

        private void SaveToCache(object state)
        {
            //First lets see if there is already a session id availible to us 
            string viewStateCacheId__1 = base.Request.Form[ViewStateCacheId];
            if (string.IsNullOrEmpty(viewStateCacheId__1))
            {
                //If there isn't then we'll be needing one. 
                viewStateCacheId__1 = Guid.NewGuid().ToString();
            }

            //Save the data into our session object 
            if ((Cache[viewStateCacheId__1] == null))
            {
                Cache.Add(viewStateCacheId__1, state, null, DateTime.Now.AddMinutes(20), System.TimeSpan.Zero, System.Web.Caching.CacheItemPriority.Normal, null);
                
            }
            else
            {
                Cache[viewStateCacheId__1] = state;
            }



            //Lastly we save the sessionid for when the page is loaded. 
           ScriptManager.RegisterHiddenField(this, ViewStateCacheId, viewStateCacheId__1);
        }

        private object LoadFromCache()
        {
            return Cache[base.Request.Form[ViewStateCacheId]];
        }

        private void SaveToSession(object state)
        {
            //First lets see if there is already a session id availible to us 
            string viewStateSessionId__1 = base.Request.Form[ViewStateSessionId];
            if (string.IsNullOrEmpty(viewStateSessionId__1))
            {
                //If there isn't then we'll be needing one. 
                viewStateSessionId__1 = Guid.NewGuid().ToString();
            }

            //Save the data into our session object 
            Session[viewStateSessionId__1] = state;

            //Lastly we save the sessionid for when the page is loaded. 
            ScriptManager.RegisterHiddenField(this, ViewStateSessionId, viewStateSessionId__1);
        }

        private object LoadFromSession()
        {
            return Session[base.Request.Form[ViewStateSessionId]];
        }

        private void CompressViewstate(object state)
        {
            //The ObjectStateFormatter is explicitly for serializing 
            //viewstate, if you're using .net 1.1 then use the LosFormatter 

            //First off, lest gets the state in a byte[] 
            ObjectStateFormatter formatter = new ObjectStateFormatter();
            byte[] bytes = null;
            using (MemoryStream writer = new MemoryStream())
            {
                formatter.Serialize(writer, state);
                bytes = writer.ToArray();
            }

            //Now we've got the raw data, lets squish the whole thing 
            using (MemoryStream output = new MemoryStream())
            {
                using (DeflateStream compressStream = new DeflateStream(output, CompressionMode.Compress, true))
                {
                    compressStream.Write(bytes, 0, bytes.Length);
                }

                //OK, now lets store the compressed data in a hidden field. 
                ScriptManager.RegisterHiddenField(this, CompressedViewStateId, Convert.ToBase64String(output.ToArray()));
            }
             
        }

        private object DecompressViewstate()
        {
            //First lets get ths raw compressed string into a byte[] 
            byte[] bytes = Convert.FromBase64String(Request.Form[CompressedViewStateId]);

            using (MemoryStream input = new MemoryStream(bytes))
            {
                //Now push the compressed data into the decompression stream 
                using (DeflateStream decompressStream = new DeflateStream(input, CompressionMode.Decompress, true))
                {
                    using (MemoryStream output = new MemoryStream())
                    {
                        //Now we wip through the decompression stream and pull our data back out 
                        byte[] buffer = new byte[256];
                        int data = 0;
                        while ((InlineAssignHelper(ref data, decompressStream.Read(buffer, 0, buffer.Length))) > 0)
                        {
                            output.Write(buffer, 0, data);
                        }

                        //Finally we convert the whole lot back into a string and convert it 
                        //back into it's original object. 
                        ObjectStateFormatter formatter = new ObjectStateFormatter();
                        return formatter.Deserialize(Convert.ToBase64String(output.ToArray()));
                    }
                }
            }
             
        }

        private static T InlineAssignHelper<T>(ref T target, T value)
        {
            target = value;
            return value;
        }
    }

    public class TwoColumnHeaderFooter : PdfPageEventHelper
    {
        // This is the contentbyte object of the writer
        PdfContentByte cb;

        // we will put the final number of pages in a template
        PdfTemplate template;

        // this is the BaseFont we are going to use for the header / footer
        BaseFont bf = null;

        // This keeps track of the creation time
        DateTime PrintTime = DateTime.Now;

        #region Properties
        private string _Title;
        public string Title
        {
            get { return _Title; }
            set { _Title = value; }
        }

        private string _HeaderLeft;
        public string HeaderLeft
        {
            get { return _HeaderLeft; }
            set { _HeaderLeft = value; }
        }

        private string _HeaderRight;
        public string HeaderRight
        {
            get { return _HeaderRight; }
            set { _HeaderRight = value; }
        }

        private Font _HeaderFont;
        public Font HeaderFont
        {
            get { return _HeaderFont; }
            set { _HeaderFont = value; }
        }

        private Font _FooterFont;
        public Font FooterFont
        {
            get { return _FooterFont; }
            set { _FooterFont = value; }
        }

        private string _FooterLeft;
        public string FooterLeft
        {
            get { return _FooterLeft; }
            set { _FooterLeft = value; }
        }
        #endregion

        // we override the onOpenDocument method
        public override void OnOpenDocument(PdfWriter writer, Document document)
        {
            try
            {
                PrintTime = DateTime.Now;
                bf = BaseFont.CreateFont(BaseFont.HELVETICA_OBLIQUE, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
                cb = writer.DirectContent;
                template = cb.CreateTemplate(50, 50);
                
            }
            catch (DocumentException de)
            {
            }
            catch (System.IO.IOException ioe)
            {
            }
        }

        //public override void OnStartPage(PdfWriter writer, Document document)
        //{
        //    base.OnStartPage(writer, document);

        //    Rectangle pageSize = document.PageSize;

        //    if (Title != string.Empty)
        //    {
        //        cb.BeginText();
        //        cb.SetFontAndSize(bf, 15);
        //        cb.SetRGBColorFill(50, 50, 200);
        //        cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetTop(40));
        //        cb.ShowText(Title);
        //        cb.EndText();
        //    }

        //    if (HeaderLeft + HeaderRight != string.Empty)
        //    {
        //        PdfPTable HeaderTable = new PdfPTable(2);
        //        HeaderTable.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE;
        //        HeaderTable.TotalWidth = pageSize.Width - 80;
        //        HeaderTable.SetWidthPercentage(new float[] { 45, 45 }, pageSize);

        //        PdfPCell HeaderLeftCell = new PdfPCell(new Phrase(8, HeaderLeft, HeaderFont));
        //        HeaderLeftCell.Padding = 5;
        //        HeaderLeftCell.PaddingBottom = 8;
        //        HeaderLeftCell.BorderWidthRight = 0;
        //        HeaderTable.AddCell(HeaderLeftCell);

        //        PdfPCell HeaderRightCell = new PdfPCell(new Phrase(8, HeaderRight, HeaderFont));
        //        HeaderRightCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;
        //        HeaderRightCell.Padding = 5;
        //        HeaderRightCell.PaddingBottom = 8;
        //        HeaderRightCell.BorderWidthLeft = 0;
        //        HeaderTable.AddCell(HeaderRightCell);

        //        cb.SetRGBColorFill(0, 0, 0);
        //        HeaderTable.WriteSelectedRows(0, -1, pageSize.GetLeft(40), pageSize.GetTop(50), cb);
        //    }
        //}

        public override void OnEndPage(PdfWriter writer, Document document)
        {

            base.OnEndPage(writer, document);

            int pageN = writer.PageNumber;
            //String text = "Page " + pageN + " of ";
            String text = "Page " + pageN;
            float len = bf.GetWidthPoint(text, 8);

            Rectangle pageSize = document.PageSize;

            cb.SetRGBColorFill(0,0,0);
            
            cb.BeginText();
            cb.SetFontAndSize(bf, 9);
            cb.SetTextMatrix(pageSize.GetLeft(400), pageSize.GetBottom(12));
            cb.ShowText(text);
            cb.EndText();

            cb.AddTemplate(template, pageSize.GetLeft(30) + len, pageSize.GetBottom(12));

            cb.BeginText();
            cb.SetFontAndSize(bf, 9);
            cb.ShowTextAligned(PdfContentByte.ALIGN_LEFT,
                 PrintTime.ToString("dd MMMM, yyyy"),
                pageSize.GetLeft(30),
                pageSize.GetBottom(12), 0);
            cb.EndText();

            cb.BeginText();
            cb.SetFontAndSize(bf, 9);
            cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
                "Fuente: AGB--CDI Dominicana",
                pageSize.GetRight(30),
                pageSize.GetBottom(12), 0);
            
            cb.EndText();

        }

        public override void OnCloseDocument(PdfWriter writer, Document document)
        {
            base.OnCloseDocument(writer, document);

            //template.BeginText();
            //template.SetFontAndSize(bf, 8);
            //template.SetTextMatrix(0, 0);
            //template.ShowText("" + (writer.PageNumber - 1));
            //template.EndText();
        }

    }
}